﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;

namespace SlamCms.Common
{
	public static class EnumerableExtensions
	{
		public static IEnumerable<T> ForEach<T>(this IEnumerable<T> collection, Action<T> action)
		{
			Ensure.ArgumentNotNull(collection, "collection");
			Ensure.ArgumentNotNull(action, "action");

			foreach (var item in collection) 
				action(item);

			return collection;
		}

		public static IEnumerable<T> GetRandom<T>(this IEnumerable<T> collection, int count)
		{
			Ensure.ArgumentNotNull(collection, "collection");
			var random = new Random(DateTime.UtcNow.Millisecond);
			var randomSortDictionary = new Dictionary<double, T>();
			foreach (var elem in collection)
				randomSortDictionary[random.NextDouble()] = elem;
			return randomSortDictionary.OrderBy(i => i.Key).Take(count).Select(i => i.Value);
		}

		public static T GetRandom<T>(this IEnumerable<T> collection)
		{
			Ensure.ArgumentNotNull(collection, "collection");
			var random = new Random(DateTime.UtcNow.Millisecond);
			var item = random.Next(collection.Count());
			return collection.ElementAt(item);
		}

		public static IEnumerable<IEnumerable<T>> Split<T>(this IEnumerable<T> source, int splitSize)
		{
			using (IEnumerator<T> enumerator = source.GetEnumerator())
			{
				while (enumerator.MoveNext())
				{
					yield return InnerSplit(enumerator, splitSize);
				}
			}
		}

		private static IEnumerable<T> InnerSplit<T>(IEnumerator<T> enumerator, int splitSize)
		{
			int count = 0;
			do
			{
				count++;
				yield return enumerator.Current;
			}
			while (count % splitSize != 0
				 && enumerator.MoveNext());
		}

		public static IEnumerable<T> OrderBy<T>(this IEnumerable<T> list, string sortExpression)
		{
			IOrderedEnumerable<T> orderedResult = default(IOrderedEnumerable<T>);
			string[] expressionParts = sortExpression.Trim().Split(' ');
			bool descending = false;
			string propertyName = "";

			if (expressionParts.Length > 0 && !String.IsNullOrEmpty(expressionParts[0]))
			{
				propertyName = expressionParts[0];
				if (expressionParts.Length > 1)
				{
					descending = expressionParts[1].ToUpper().StartsWith("DESC");
				}

				PropertyInfo property = typeof(T).GetProperty(propertyName);
				if (property != null)
				{
					if (descending)
					{
						orderedResult = list.OrderByDescending(i => property.GetValue(i, null));
					}
					else
					{
						orderedResult = list.OrderBy(i => property.GetValue(i, null));
					}
				}
			}

			return orderedResult;
		}
	}
}
